package yunjiao.javatutorials.guava.concurrent.spring;

import com.google.common.util.concurrent.AbstractIdleService;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * 数据库连接服务, 使用@PostConstruct
 *
 * @author yangyunjiao
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DatabaseConnectionService extends AbstractIdleService {

    private final DataSource dataSource;
    private BlockingQueue<Connection> connectionPool;
    private final ServiceProperties serviceProperties;

    @Override
    protected void startUp() throws Exception {
        log.info("Spring Boot - Starting database connection pool");

        int poolSize = serviceProperties.getDatabasePoolSize();
        connectionPool = new LinkedBlockingQueue<>(poolSize);

        // 初始化连接池
        for (int i = 0; i < poolSize; i++) {
            Connection connection = dataSource.getConnection();
            // 配置连接
            connection.setAutoCommit(true);
            connectionPool.offer(connection);
        }

        log.info("Database connection pool ready with " + poolSize + " connections");
    }

    @Override
    protected void shutDown() throws Exception {
        log.info("Spring Boot - Shutting down database connection pool");

        if (connectionPool != null) {
            Connection connection;
            int closedCount = 0;
            while ((connection = connectionPool.poll()) != null) {
                try {
                    if (!connection.isClosed()) {
                        connection.close();
                        closedCount++;
                    }
                } catch (SQLException e) {
                    log.error("Error closing connection: " + e.getMessage());
                }
            }
            log.info("Closed " + closedCount + " database connections");
        }
    }

    public Connection getConnection() throws InterruptedException, SQLException {
        if (!isRunning()) {
            throw new IllegalStateException("Database service is not running");
        }

        Connection connection = connectionPool.take();

        // 验证连接是否有效
        if (connection.isClosed() || !connection.isValid(2)) {
            connection = dataSource.getConnection();
        }

        return connection;
    }

    public void releaseConnection(Connection connection) throws SQLException {
        if (connection != null && !connection.isClosed() && isRunning()) {
            // 重置连接状态
            if (!connection.getAutoCommit()) {
                connection.rollback();
                connection.setAutoCommit(true);
            }
            connectionPool.offer(connection);
        }
    }

    public int getAvailableConnections() {
        return connectionPool != null ? connectionPool.size() : 0;
    }

    @PostConstruct
    public void startService() {
        log.info("PostConstruct - Starting service");
        this.startAsync().awaitRunning();
    }

    @PreDestroy
    public void stopService() {
        log.info("PreDestroy - Stopping service");
        this.stopAsync().awaitTerminated();
    }
}
